package com.jservice;

import com.baidu.ueditor.UeditorConfigKit;
import com.google.common.collect.Maps;
import com.jfinal.config.*;
import com.jfinal.core.JFinal;
import com.jfinal.kit.PathKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.CaseInsensitiveContainerFactory;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.ehcache.EhCachePlugin;
import com.jfinal.render.FreeMarkerRender;
import com.jservice.framework.authc.AuthcUtil;
import com.jservice.framework.cache.JCachePlugin;
import com.jservice.framework.dto.Setting;
import com.jservice.framework.freemarker.directive.FlashMessageDirective;
import com.jservice.framework.freemarker.directive.FooterDirective;
import com.jservice.framework.freemarker.directive.PaginationDirective;
import com.jservice.framework.freemarker.method.AbbreviateMethod;
import com.jservice.framework.freemarker.method.CurrencyMethod;
import com.jservice.framework.freemarker.method.MessageMethod;
import com.jservice.framework.interceptor.FlashMessageInterceptor;
import com.jservice.framework.message.plugin.MessagePlugin;
import com.jservice.framework.route.AutoBindRoutes;
import com.jservice.framework.servlet.ServletContextHandler;
import com.jservice.framework.spring.SpringDataSourcePlugin;
import com.jservice.framework.spring.SpringPlugin;
import com.jservice.framework.utils.ClassUtils;
import com.jservice.model.core.JModelMapping;
import com.jservice.model.core.Table;
import com.jservice.web.base.JBaseController;
import com.jservice.web.editor.NeditorController;
import com.jservice.web.editor.NeditorFileManager;
import freemarker.template.Configuration;
import freemarker.template.TemplateModelException;
import freemarker.template.utility.StandardCompress;
import net.sf.ehcache.config.ConfigurationFactory;
import net.sf.ehcache.config.DiskStoreConfiguration;
import org.apache.commons.lang3.StringUtils;
import org.jdom.JDOMException;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

public class WebConfigRun extends JFinalConfig{

    Log log = Log.getLog(WebConfigRun.class);

    private Routes routes;

    @Override
        public void configConstant(Constants me) {
            loadPropertyFile("system.properties");
            me.setDevMode(getPropertyToBoolean("jfinal.devmode"));
            me.setEncoding(getProperty("url_escaping_charset"));
        }

    @Override
    public void configRoute(Routes me) {
        this.routes = me;
        me.add("/ueditor/api", NeditorController.class);
        routes.add(new AutoBindRoutes().addExcludeClasses(JBaseController.class).autoScan(false));
    }

    @Override
    public void configPlugin(Plugins me) {
        me.add(createEhCachePlugin());
        String [] configurations = new String [] {"classpath:applicationContext.xml"};
        SpringPlugin springPlugin = new SpringPlugin(configurations);
        me.add(springPlugin);
        JCachePlugin cachePlugin = new JCachePlugin();
        me.add(cachePlugin);
        ActiveRecordPlugin activeRecordPlugin = new ActiveRecordPlugin(new SpringDataSourcePlugin());
        activeRecordPlugin.setCache(cachePlugin.getCache());
        activeRecordPlugin.setShowSql(true);
        activeRecordPlugin.setContainerFactory(new CaseInsensitiveContainerFactory(true));

        List<Class<Model>> modelClassList = ClassUtils.scanSubClass(Model.class);
        if (modelClassList != null) {
            for (Class<?> clazz : modelClassList) {
                Table tb = clazz.getAnnotation(Table.class);
                if (tb == null)
                    continue;
                if (StringUtils.isNotBlank(tb.primaryKey())) {
                    activeRecordPlugin.addMapping(tb.tableName(), tb.primaryKey(), (Class<? extends Model<?>>) clazz);
                } else {
                    activeRecordPlugin.addMapping(tb.tableName(), (Class<? extends Model<?>>) clazz);
                }

                JModelMapping.me().mapping(clazz.getSimpleName().toLowerCase(), tb.tableName());
            }
        }
        me.add(activeRecordPlugin);
        me.add(new MessagePlugin());



    }

    @Override
    public void configInterceptor(Interceptors me) {
        me.add(new FlashMessageInterceptor());
    }

    @Override
    public void configHandler(Handlers me) {
        me.add(new ServletContextHandler());
    }

    @Override
    public void afterJFinalStart() {

        Configuration cf = FreeMarkerRender.getConfiguration();
        Map<String, Object> map = Maps.newHashMap();
//        map.put("imgDomain", PropKit.get("img_domain"));
        map.put("base", JFinal.me().getContextPath());
        map.put("locale", getProperty("locale"));
        map.put("compress", StandardCompress.INSTANCE);
        try {
            cf.setSharedVaribles(map);
        } catch (TemplateModelException e) {
            e.printStackTrace();
        }
        if(getPropertyToBoolean("jfinal.devmode")){
            cf.setTemplateUpdateDelay(getPropertyToInt("template.update_delay", 0));
        }else{
            cf.setTemplateUpdateDelay(getPropertyToInt("template.update_delay", 300));
        }
        cf.setDefaultEncoding(getProperty("template.encoding"));
        cf.setURLEscapingCharset(getProperty("url_escaping_charset"));
        cf.setTagSyntax(Configuration.SQUARE_BRACKET_TAG_SYNTAX);
        cf.setWhitespaceStripping(true);
        cf.setClassicCompatible(true);
        cf.setNumberFormat(getProperty("template.number_format"));
        cf.setBooleanFormat(getProperty("template.boolean_format"));
        cf.setDateTimeFormat(getProperty("template.datetime_format"));
        cf.setDateFormat(getProperty("template.date_format"));
        cf.setTimeFormat(getProperty("template.time_format"));

        cf.setSharedVariable("flash_message",new FlashMessageDirective());
        cf.setSharedVariable("message",new MessageMethod());
        cf.setSharedVariable("abbreviate",new AbbreviateMethod());
        cf.setSharedVariable("currency",new CurrencyMethod());
        cf.setSharedVariable("pagination",new PaginationDirective());
        cf.setSharedVariable("tab",new FooterDirective());
        try {
            cf.setSharedVariable("setting", Setting.getInstance());
        } catch (TemplateModelException e) {
            e.printStackTrace();
        }
        cf.setServletContextForTemplateLoading(JFinal.me().getServletContext(), getProperty("template.loader_path"));

        String fileName = "authc.xml";
        try {
            AuthcUtil.initAuthcConfig(fileName);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JDOMException e) {
            e.printStackTrace();
        }

        UeditorConfigKit.setFileManager(new NeditorFileManager());

        log.info("  web server is ready!!");
        super.afterJFinalStart();
    }
    
    /**
	 * 运行此 main 方法可以启动项目，此main方法可以放置在任意的Class类定义中，不一定要放于此
	 * 
	 * 使用本方法启动过第一次以后，会在开发工具的 debug、run config 中自动生成
	 * 一条启动配置，可对该自动生成的配置再添加额外的配置项，例如 VM argument 可配置为：
	 * -XX:PermSize=64M -XX:MaxPermSize=256M
	 */
	public static void main(String[] args) {
		/**
		 * 特别注意：Eclipse 之下建议的启动方式
		 */
		JFinal.start("src/main/webapp", 8090, "/", 5);
		
		/**
		 * 特别注意：IDEA 之下建议的启动方式，仅比 eclipse 之下少了最后一个参数
		 */
		// JFinal.start("src/main/webapp", 80, "/");
	}

    private EhCachePlugin createEhCachePlugin() {
        String ehcacheDiskStorePath = PathKit.getRootClassPath();
        File pathFile = new File(ehcacheDiskStorePath, "ehcache");

        net.sf.ehcache.config.Configuration cfg = ConfigurationFactory.parseConfiguration();
        cfg.addDiskStore(new DiskStoreConfiguration().path(pathFile.getAbsolutePath()));
        return new EhCachePlugin(cfg);
    }
}
